#include "stdafx.h"
#include "PopupWnd.h"
#include "Settings.h"

CScreenDC CPopupWnd::s_popupbuf;

void CPopupWnd::Show(const CRect& rcStart, const CRect& rcEnd, DWORD dwTime)
{
  if (IsWindowVisible())
  {
    MoveWindow(rcEnd);
    return;
  }

  m_rcStart = rcStart;
  m_rcEnd = rcEnd;
  m_bShow = true;
  if (dwTime == 0)
  {
    StopTransition();
  }
  else
  {
    MoveWindow(rcEnd, FALSE);
    SendMessage(WM_HDCPAINT, (WPARAM)s_popupbuf.m_hDC);

    m_tDuration = dwTime;
    m_tStart = ::GetTickCount();
    m_tmrTransition.Start(POPUP_WND_REFRESH_RATE);
    SetCapture();
    MoveWindow(m_rcStart, FALSE);
    for(HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
    {
      ::ShowWindow(hWndChild, SW_HIDE);
    }
    ShowWindow(SW_SHOW);
  }
}

void CPopupWnd::Hide(const CRect& rcEnd, DWORD dwTime)
{
  if (!IsWindowVisible())
  {
    MoveWindow(rcEnd, FALSE);
    return;
  }

  m_rcEnd = rcEnd;
  GetWindowRect(&m_rcStart);
  CWindow parent = GetParent();
  if (parent.m_hWnd)
    parent.ScreenToClient(&m_rcStart);
  m_bShow = false;
  if (dwTime == 0)
  {
    StopTransition();
  }
  else
  {
    SendMessage(WM_HDCPAINT, (WPARAM)s_popupbuf.m_hDC);

    m_tDuration = dwTime;
    m_tStart = ::GetTickCount();
    m_tmrTransition.Start(POPUP_WND_REFRESH_RATE);
    SetCapture();
    for(HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
    {
      ::ShowWindow(hWndChild, SW_HIDE);
    }
  }
}

void CPopupWnd::OnTransitionTimer(UINT uTimer, DWORD dwTime)
{
  double d = (double)(::GetTickCount() - m_tStart) / m_tDuration;

  if (d >= 1.0)
  {
    MoveWindow(m_rcEnd);
    StopTransition();
    return;
  }

  double cubic = pow(d - 1, 3) + 1;

  CRect rc;
  rc.left = m_rcStart.left - (int)((m_rcStart.left - m_rcEnd.left) * cubic);
  rc.right = m_rcStart.right - (int)((m_rcStart.right - m_rcEnd.right) * cubic);
  rc.top = m_rcStart.top - (int)((m_rcStart.top - m_rcEnd.top) * cubic);
  rc.bottom = m_rcStart.bottom - (int)((m_rcStart.bottom - m_rcEnd.bottom) * cubic);
  MoveWindow(rc);
}

void CPopupWnd::DoPaint(CDCHandle dc, const CRect& rClip)
{
  if (m_tmrTransition.IsActive())
  {
    CRect rc;
    GetWindowRect(&rc);
    CWindow parent = GetParent();
    if (parent.m_hWnd)
      parent.ScreenToClient(&rc);
    /*
    dc.StretchBlt(0, 0, rc.Width(), rc.Height(),
                  CTheme::popupbuf, 0, 0, bShow ? m_rcEnd.Width() : m_rcStart.Width(), bShow ? m_rcEnd.Height() : m_rcStart.Height(),
                  SRCCOPY);
    */
    dc.BitBlt(0, 0, rc.Width(), rc.Height(), s_popupbuf, 0, 0, SRCCOPY);
  }
  else
  {
    CBaseWindow::DoPaint(dc, rClip);
  }
}

void CPopupWnd::StopTransition()
{
  ReleaseCapture();
  m_tmrTransition.Stop();
  if (m_bShow)
  {
    for(HWND hWndChild = ::GetWindow(m_hWnd, GW_CHILD); hWndChild != NULL; hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT))
    {
      ::ShowWindow(hWndChild, SW_SHOW);
    }
  }
  else
  {
    ShowWindow(SW_HIDE);
  }
}

int CModalPopupWnd::DoModal()
{
  m_result = IDCANCEL;
  m_endDialog = false;
  m_dwHideTime = 0;

  CWindow parent = GetParent();
  if (parent.m_hWnd)
    parent.EnableWindow(FALSE);

  ShowWindow(SW_SHOW);
  ModalLoop();
  if (parent.m_hWnd)
    parent.EnableWindow(TRUE);
  return m_result;
}

int CModalPopupWnd::DoModal(const CRect& rcStart, DWORD dwShowTime, DWORD dwHideTime)
{
  CRect rcEnd;
  CWindow parent = GetParent();
  if (parent.m_hWnd)
  {
    parent.GetClientRect(&rcEnd);
  }
  else
  {
    SystemParametersInfo(SPI_GETWORKAREA, 0, &rcEnd, FALSE);
    if (CSettings::IsSmartphone())
    { // Overlap menubar
      rcEnd.bottom = ::GetSystemMetrics(SM_CYSCREEN);
    }
  }
  return DoModal(rcStart, rcEnd, dwShowTime, dwHideTime);
}

int CModalPopupWnd::DoModal(const CRect& rcStart, const CRect& rcEnd, DWORD dwShowTime, DWORD dwHideTime)
{
  m_result = IDCANCEL;
  m_endDialog = false;
  m_dwHideTime = dwHideTime;

  Show(rcStart, rcEnd, dwShowTime);
  ModalLoop();
  return m_result;
}

void CModalPopupWnd::StopTransition()
{
  CWindow parent = GetParent();
  if (parent.m_hWnd)
    parent.EnableWindow(!m_bShow);

  CPopupWnd::StopTransition();

  if (!m_bShow)
    DestroyWindow();
}

void CModalPopupWnd::ModalLoop()
{
  // message loop
  MSG msg;
  while (!m_endDialog && ::GetMessage(&msg, NULL, 0, 0))
  {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
  }
  if (msg.message == WM_QUIT)
  {
    // passthrough for main loop
    PostQuitMessage(msg.wParam);
  }
}
